package com.jfirer.mvc.core.route.impl;

import com.jfirer.mvc.core.route.RouteNode;
import com.jfirer.mvc.core.route.Router;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class RouteNodeImpl implements RouteNode
{
    
    private Map<String, RouteNode> notes    = new HashMap<String, RouteNode>();
    private RouteNode              valueNode;
    private String                 url;
    private boolean                isTermination;
    private List<Router>           _routers = new LinkedList<Router>();
    private Router[]               routers;
    
    public RouteNodeImpl(String url)
    {
        this.url = url;
    }
    
    @Override
    public Router route(String[] paths, int index, HttpServletRequest request)
    {
        if (index == paths.length)
        {
            if (isTermination)
            {
                for (Router each : routers)
                {
                    if (each.match(request))
                    {
                        return each;
                    }
                }
                return null;
            }
            else
            {
                return null;
            }
        }
        String match = paths[index];
        RouteNode node = notes.get(match);
        index += 1;
        return node == null ? //
                (valueNode == null ? null : valueNode.route(paths, index, request)) //
                : node.route(paths, index, request);
    }
    
    @Override
    public Router resolve(String name, String[] paths, int index, String httpMethod, String[] headerRules)
    {
        if (index == paths.length)
        {
            isTermination = true;
            Router router = new RouterImpl(paths, name, url, httpMethod, headerRules);
            for (Router each : this._routers)
            {
                if (each.equals(router))
                {
                    throw new UnsupportedOperationException("存在相同的路由规则，请检查:" + each.toString());
                }
            }
            this._routers.add(router);
            return router;
        }
        String match = paths[index];
        if (match.startsWith("{") && match.endsWith("}"))
        {
            if (valueNode == null)
            {
                String value = "";
                for (int i = 0; i <= index; i++)
                {
                    value += "/" + paths[i];
                }
                valueNode = new RouteNodeImpl(value);
            }
            index += 1;
            return valueNode.resolve(name, paths,index , httpMethod, headerRules);
        }
        else
        {
            RouteNode exist = notes.get(match);
            if (exist != null)
            {
                index += 1;
                return exist.resolve(name, paths, index, httpMethod, headerRules);
            }
            else
            {
                String value = "";
                for (int i = 0; i <= index; i++)
                {
                    value += "/" + paths[i];
                }
                RouteNode node = new RouteNodeImpl(value);
                notes.put(match, node);
                index += 1;
                return node.resolve(name, paths, index, httpMethod, headerRules);
            }
        }
    }
    
    @Override
    public String toString()
    {
        return url;
    }
    
    @Override
    public void finishResolve()
    {
        routers = _routers.toArray(new RouterImpl[_routers.size()]);
        if (valueNode != null)
        {
            valueNode.finishResolve();
        }
        for (RouteNode each : notes.values())
        {
            each.finishResolve();
        }
    }
    
}
